package com.learn.security.modules.security;

import cn.hutool.core.collection.CollUtil;
import com.learn.security.modules.user.entity.UserInfo;
import com.learn.security.modules.user.service.IUserInfoService;
import com.learn.security.modules.vo.UserDto;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * created by yuanjunjie on 2019/6/10 3:40 PM
 * @author lee
 */
@Slf4j
@Service("customUserDetailsService")
public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {

    @Autowired
    private IUserInfoService userInfoService;

    /**
     * 手机号登录
     *
     * @param loginUserType
     * @param user
     * @return UserDetails
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserBySocial(LoginUserType loginUserType, UserDto user) throws UsernameNotFoundException {
        // 保存登录用户
        UserInfo userInfo = saveUser(user);
        // 返回登录包装类
        return new LoginUser(UserDto.toUser(userInfo),
                loginUserType,
                user.getMobile(),
                "",
                true,
                true,
                true,
                true,
                AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN"));
    }

    /**
     * 保存登录用户
     * @param user
     */
    private UserInfo saveUser(UserDto user) {
        List<UserInfo> list = userInfoService.lambdaQuery()
                .eq(UserInfo::getMobile, user.getMobile())
                .eq(UserInfo::getPlateNo, user.getPlateNo())
                .list();
        if (CollUtil.isEmpty(list)) {
            UserInfo userInfo = new UserInfo();
            userInfo.setPlateNo(user.getPlateNo());
            userInfo.setMobile(user.getMobile());
            userInfo.setOpenId(user.getOpenId());
            userInfo.setCreateId(1L);
            userInfo.setCreateTime(LocalDateTime.now());
            userInfo.setUpdateId(1L);
            userInfo.setUpdateTime(LocalDateTime.now());
            userInfo.insert();
            return userInfo;
        } else {
            UserInfo userInfo = list.get(0);
            userInfo.setOpenId(user.getOpenId());
            userInfo.setUpdateId(userInfo.getId());
            userInfo.setUpdateTime(LocalDateTime.now());
            userInfo.updateById();
            return userInfo;
        }
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 用户名密码登录
        return new LoginUser(null,
                LoginUserType.USERNAME,
                "admin",
                "888888",
                true,
                true,
                true,
                true,
                AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN"));
    }

    @Override
    public UserDetails loadUserByOpenId(LoginUserType loginUserType, WxMpUser mpUser) throws AuthenticationException {
        List<UserInfo> list = userInfoService.lambdaQuery()
                .eq(UserInfo::getOpenId, mpUser.getOpenId())
                .list();
        if (CollUtil.isEmpty(list)) {
            throw new AuthenticationCredentialsNotFoundException("未查询到该openid的用户");
        }
        if (list.size() > 1) {
            throw new BadCredentialsException("openid查询出多条数据");
        }
        UserInfo userInfo = list.get(0);
        userInfo.setUpdateId(userInfo.getId());
        userInfo.setUpdateTime(LocalDateTime.now());
        userInfo.updateById();
        return new LoginUser(UserDto.toUser(userInfo),
                loginUserType,
                userInfo.getMobile(),
                "",
                true,
                true,
                true,
                true,
                AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN"));
    }
}
